//
// Created by 余代宸 -yudaichen on 2021/12/18
// QQ-E-MAIL:250074249@qq.com
//
#include <ctype.h>
#include "../include/socket.h"

_Noreturn void server() {
#ifdef __unix__
	int lfd = 0, cfd = 0, ret = 0, i = 0;
	char buffer[BUFSIZ], clientIp[1024];
	struct sockaddr_in serverAddress, clientAddress;  // 定义服务器地址结构 和 客户端地址结构
	socklen_t clientAddressLength;                  // 客户端地址结构大小
	serverAddress.sin_family = AF_INET;                // IPv4
	serverAddress.sin_port = htons(SERV_PORT);        // 转为网络字节序的 端口号
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);    // 获取本机任意有效IP
	lfd = socket(AF_INET, SOCK_STREAM, 0);        //创建一个 socket
	if (lfd == -1) {
		logUtils("socket error",LOG_DEBUG);
	}
	bind(lfd, (struct sockaddr *) &serverAddress, sizeof(serverAddress));//给服务器socket绑定地址结构（IP+port)
	listen(lfd, 128);                    //	设置监听上限
	clientAddressLength = sizeof(clientAddress);    // 	获取客户端地址结构大小
	cfd = accept(lfd, (struct sockaddr *) &clientAddress, &clientAddressLength);    // 阻塞等待客户端连接请求
	if (cfd == -1) {
		logUtils("accept error",LOG_DEBUG);
	}
	printf("client ip:%s port:%d\n",
	       inet_ntop(AF_INET, &clientAddress.sin_addr.s_addr, clientIp, sizeof(clientIp)),
	       ntohs(clientAddress.sin_port));            // 根据accept传出参数，获取客户端 ip 和 port
	while (1) {
		ret = read(cfd, buffer, sizeof(buffer));        // 读客户端数据
		write(STDOUT_FILENO, buffer, ret);            // 写到屏幕查看
		for (i = 0; i < ret; i++) {                // 小写 -- 大写
			buffer[i] = toupper(buffer[i]);
		}
		write(cfd, buffer, ret);                    // 将大写，写回给客户端。
	}
	close(lfd);
	close(cfd);
#endif
}


void client() {
#ifdef __unix__
	int cfd;
	int count = 10;
	char buf[BUFSIZ];
	struct sockaddr_in serverAddress;          //服务器地址结构
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(SERV_PORT);
	inet_pton(AF_INET, "127.0.0.1", &serverAddress.sin_addr.s_addr);
	cfd = socket(AF_INET, SOCK_STREAM, 0);
	if (cfd == -1) {
		logUtils("client socket error",LOG_DEBUG);
	}
	int ret = connect(cfd, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
	if (ret != 0) {
		logUtils("client connect err",LOG_DEBUG);
	}
	while (--count) {
		write(cfd, "hello\n", 6);
		ret = read(cfd, buf, sizeof(buf));
		write(STDOUT_FILENO, buf, ret);
		sleep(1);
	}
	close(cfd);
#endif // __unix__
}

/**
 * @note
 * pthread_join : 多线程阻塞 （阻塞函数内部未执行到的代码）
 * pthread_detach : 多线程非阻塞 （主线程与子线程分离，子线程结束后，资源自动回收）
 */
void domain() {
#ifdef __unix__
	pthread_t serverThread, clientThread;
	if (pthread_create(&serverThread, NULL, (void *) &server, NULL) != 0) {
		logUtils("serverThread create error",LOG_DEBUG);
	} else {
		logUtils("serverThread create success",LOG_DEBUG);
	}
	if (pthread_detach(serverThread) != 0) {
		logUtils("serverThread detach error",LOG_DEBUG);
	}
	if (pthread_create(&clientThread, NULL, (void *) &client, NULL) != 0) {
		logUtils("clientThread create error",LOG_DEBUG);
	} else {
		logUtils("clientThread create success",LOG_DEBUG);
	}
	if (pthread_detach(clientThread) != 0) {
		logUtils("clientThread detach error",LOG_DEBUG);
	}
	sleep(100000);
#endif //__unix__
}